#include <stdio.h>
#include <stdlib.h>

#define _UART0					0
#define _UART1					1
#define _UART2					2

#define TRUE					1
#define FALSE					0

#define BUFFER_SIZE 			8
#define BUFFER_STARTING_POS 	0

// global variables
char g_buffUART0 [BUFFER_SIZE];
char g_buffUART1 [BUFFER_SIZE];
char g_buffUART2 [BUFFER_SIZE];

int g_bufferUserPointer0 = 0;
int g_bufferUserPointer1 = 0;
int g_bufferUserPointer2 = 0;

int g_bufferPointerPos0 = 0;
int g_bufferPointerPos1 = 0;
int g_bufferPointerPos2 = 0;

int g_buffCnt0 = 0;
int g_buffCnt1 = 0;
int g_buffCnt2 = 0;

struct UART_Data_Buffer {
	char * uartArray;		// = malloc(sizeof uartArray);
	int * userPointer;
	int * bufferPointerPos;	// = malloc(sizeof bufferPointerPos);
	int * buffCnt;	
};

struct UART_Data_Buffer getUartDataBuffer( int uartSelect )
{
	struct UART_Data_Buffer uartBuffer;
	
	switch(uartSelect)
	{
		case _UART0:
			uartBuffer.uartArray 			= g_buffUART0;
			uartBuffer.userPointer 			= &g_bufferUserPointer0;
			uartBuffer.bufferPointerPos 	= &g_bufferPointerPos0;
			uartBuffer.buffCnt				= &g_buffCnt0;
			break;
		case _UART1:
			uartBuffer.uartArray 			= g_buffUART1;
			uartBuffer.userPointer 			= &g_bufferUserPointer1;
			uartBuffer.bufferPointerPos 	= &g_bufferPointerPos1;
			uartBuffer.buffCnt				= &g_buffCnt1;			
			break;
		case _UART2:
			uartBuffer.uartArray 			= g_buffUART2;
			uartBuffer.userPointer 			= &g_bufferUserPointer2;
			uartBuffer.bufferPointerPos 	= &g_bufferPointerPos2;
			uartBuffer.buffCnt				= &g_buffCnt2;			
			break;			
	}
	
	return uartBuffer;
}

// TODO: how this is currently set up is that if the buffer is full, no more
// characters will be able to be added to it.
void addCharToBuffer(int uartSelect, char inChar)
{
	struct UART_Data_Buffer uartBuffer;
	
	uartBuffer = getUartDataBuffer( uartSelect );
	
	if ( (*uartBuffer.buffCnt) < BUFFER_SIZE )
	{
		
		*( uartBuffer.uartArray + *uartBuffer.bufferPointerPos ) = inChar;	

		//printf("\nuart%d[%d] = %c", uartSelect, *bufferPointerPos, *( uartArray + *bufferPointerPos ) );
		
		if ((*uartBuffer.bufferPointerPos) == BUFFER_SIZE - 1 )
			(*uartBuffer.bufferPointerPos ) = 0;
		else
			(*uartBuffer.bufferPointerPos )++;
		
		(*uartBuffer.buffCnt)++;
		
	}
	else
	{
		//printf("\nbuffer is full");
	}
}

void printArray(int uartSelect)
{

	struct UART_Data_Buffer uartBuffer;
	
	uartBuffer = getUartDataBuffer( uartSelect );
	
	while( *uartBuffer.buffCnt >= 1 )
	{
		//printf("\nuart%d[%d] = %c   <%d>", uartSelect, *uartBuffer.userPointer, *( uartBuffer.uartArray + *uartBuffer.userPointer ) , *uartBuffer.buffCnt );		
		
		(*uartBuffer.userPointer) = ((*uartBuffer.userPointer) + 1 == BUFFER_SIZE ) ? 0 : ((*uartBuffer.userPointer) + 1);
		
		if ( (*uartBuffer.buffCnt) == BUFFER_SIZE ) 
			(*uartBuffer.buffCnt)--;
			
		(*uartBuffer.buffCnt)--;
		
	}
}

int getBuffCnt(int uartSelect)
{
	struct UART_Data_Buffer uartBuffer;
	
	uartBuffer = getUartDataBuffer( uartSelect );
	
	return *(uartBuffer.buffCnt);
}

int main()
{
	addCharToBuffer(_UART1, 'Q');
		printf("-");printf("\nvalues added userPtr %d    ptrPos %d", g_bufferUserPointer1, g_bufferPointerPos1);
	addCharToBuffer(_UART1, 'U');
		printf("-");printf("\nvalues added userPtr %d    ptrPos %d", g_bufferUserPointer1, g_bufferPointerPos1);
	addCharToBuffer(_UART1, 'E');
		printf("-");printf("\nvalues added userPtr %d    ptrPos %d", g_bufferUserPointer1, g_bufferPointerPos1);
	addCharToBuffer(_UART1, 'E');
		printf("-");printf("\nvalues added userPtr %d    ptrPos %d", g_bufferUserPointer1, g_bufferPointerPos1);
	addCharToBuffer(_UART1, 'N');
		printf("-");printf("\nvalues added userPtr %d    ptrPos %d", g_bufferUserPointer1, g_bufferPointerPos1);
	addCharToBuffer(_UART1, 'A');
		printf("-");printf("\nvalues added userPtr %d    ptrPos %d", g_bufferUserPointer1, g_bufferPointerPos1);
	addCharToBuffer(_UART1, 'B');	
		printf("-");printf("\nvalues added userPtr %d    ptrPos %d", g_bufferUserPointer1, g_bufferPointerPos1);
	addCharToBuffer(_UART1, 'C');
		printf("-");printf("\nvalues added userPtr %d    ptrPos %d", g_bufferUserPointer1, g_bufferPointerPos1);
	addCharToBuffer(_UART1, 'D');
		printf("-");printf("\nvalues added userPtr %d    ptrPos %d", g_bufferUserPointer1, g_bufferPointerPos1);
		printArray( _UART1 );
		printf("\n");
		printf("\n");		
	addCharToBuffer(_UART1, 'E');
		printf("-");printf("\nvalues added userPtr %d    ptrPos %d", g_bufferUserPointer1, g_bufferPointerPos1);
	addCharToBuffer(_UART1, 'F');
		printf("-");printf("\nvalues added userPtr %d    ptrPos %d", g_bufferUserPointer1, g_bufferPointerPos1);
	printArray( _UART1 );
	//printf("\n\nvalues added userPtr %d    ptrPos %d\n\n", g_bufferUserPointer1, g_bufferPointerPos1);
	
	
	
	printf("\nDONE");
}